//
//  UIView+ZMLayout.m
//  ZMKitDemo
//
//  Created by zm on 2018/6/13.
//  Copyright © 2018年 zm. All rights reserved.
//

#import "UIView+ZMLayout.h"
#import <objc/runtime.h>

static void *kUIViewLayoutMethodPropertyBottomGap = &kUIViewLayoutMethodPropertyBottomGap;
static void *kUIViewLayoutMethodPropertyTopGap = &kUIViewLayoutMethodPropertyTopGap;
static void *kUIViewLayoutMethodPropertyLeftGap = &kUIViewLayoutMethodPropertyLeftGap;
static void *kUIViewLayoutMethodPropertyRightGap = &kUIViewLayoutMethodPropertyRightGap;

static void *kUIViewTouchExtendInset = &kUIViewTouchExtendInset;


@implementation UIView (ZMLayout)

#pragma mark- 点击响应区域
#pragma mark TouchExtentInset

void swizzle(Class class, SEL oldSel, SEL newSel) {
    Method oldMethod = class_getInstanceMethod(class, oldSel);
    Method newMethod = class_getInstanceMethod(class, newSel);
    
    IMP impOld = method_getImplementation(oldMethod);
    IMP impNew = method_getImplementation(newMethod);

    const char *typeOld = method_getTypeEncoding(oldMethod);
    const char *typeNew = method_getTypeEncoding(newMethod);

    if (class_addMethod(class, oldSel,impNew, typeNew)) {
        class_replaceMethod(class, newSel, impOld, typeOld);
    } else {
        method_exchangeImplementations(oldMethod, newMethod);
    }
}

+ (void)load {
    swizzle(self, @selector(pointInside:withEvent:), @selector(zm_pointInside:withEvent:));
}

- (BOOL)zm_pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    if (UIEdgeInsetsEqualToEdgeInsets(self.touchExtendInset, UIEdgeInsetsZero) || self.hidden ||
        ([self isKindOfClass:UIControl.class] && !((UIControl *)self).enabled)) {
        return [self zm_pointInside:point withEvent:event];
    }
    CGRect hitFrame = UIEdgeInsetsInsetRect(self.bounds, self.touchExtendInset);
    hitFrame.size.width = MAX(hitFrame.size.width, 0);
    hitFrame.size.height = MAX(hitFrame.size.height, 0);
    return CGRectContainsPoint(hitFrame, point);
}


- (void)setTouchExtendInset:(UIEdgeInsets)touchExtendInset {
    objc_setAssociatedObject(self, &kUIViewTouchExtendInset, [NSValue valueWithUIEdgeInsets:touchExtendInset], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIEdgeInsets)touchExtendInset {
    return [objc_getAssociatedObject(self, &kUIViewTouchExtendInset) UIEdgeInsetsValue];
}

#pragma mark- 坐标
#pragma mark Getter
- (CGFloat)zm_height {
    return self.frame.size.height;
}

- (CGFloat)zm_width {
    return self.frame.size.width;
}

- (CGPoint)zm_origin {
    return self.frame.origin;
}

- (CGSize)zm_size {
    return self.frame.size;
}

- (CGFloat)zm_centerX {
    return self.center.x;
}

- (CGFloat)zm_centerY {
    return self.center.y;
}

- (CGFloat)zm_x {
    return self.frame.origin.x;
}

- (CGFloat)zm_y {
    return self.frame.origin.y;
}


- (CGFloat)zm_left {
    return self.zm_x;
}

- (CGFloat)zm_right {
    return self.zm_width + self.zm_x;
}

- (CGFloat)zm_top {
    return self.zm_y;
}

- (CGFloat)zm_bottom  {
    return self.zm_height + self.zm_y;
}

#pragma mark Setter
- (void)setZm_height:(CGFloat)zm_height {
    self.frame = CGRectMake(self.zm_x, self.zm_y, self.zm_width, zm_height);
}

- (void)setZm_width:(CGFloat)zm_width {
    self.frame = CGRectMake(self.zm_x, self.zm_y, zm_width, self.zm_width);
}

- (void)setZm_size:(CGSize)zm_size {
    self.frame = CGRectMake(self.zm_x, self.zm_y, zm_size.width, zm_size.height);
}

- (void)setZm_centerX:(CGFloat)zm_centerX {
    self.center = CGPointMake(zm_centerX, self.zm_centerY);
}

- (void)setZm_centerY:(CGFloat)zm_centerY {
    self.center = CGPointMake(self.zm_centerX, zm_centerY);
}

- (void)setZm_x:(CGFloat)zm_x {
    self.frame = CGRectMake(zm_x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
}

- (void)setZm_y:(CGFloat)zm_y {
    self.frame = CGRectMake(self.frame.origin.x, zm_y, self.frame.size.width, self.frame.size.height);
}

- (void)setZm_origin:(CGPoint)zm_origin {
    self.frame = CGRectMake(zm_origin.x, zm_origin.y, self.zm_width, self.zm_height);
}


- (void)setZm_left:(CGFloat)zm_left {
    self.zm_x = zm_left;
}

- (void)setZm_right:(CGFloat)zm_right {
    self.zm_x = zm_right - self.zm_width;
}

- (void)setZm_top:(CGFloat)zm_top {
    self.zm_y = zm_top;
}

- (void)setZm_bottom:(CGFloat)zm_bottom {
    self.zm_y = zm_bottom - self.zm_height;
}



#pragma mark Equal
- (void)heightEqualToView:(UIView *)view {
    self.zm_height = view.zm_height;
}

- (void)widthEqualToView:(UIView *)view {
    self.zm_width = view.zm_width;
}

- (void)sizeEqualToView:(UIView *)view {
    self.frame = CGRectMake(self.zm_x, self.zm_y, view.zm_width, view.zm_height);
}

- (void)centerXEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewCenterPoint = [superView convertPoint:view.center toView:self.topSuperView];
    CGPoint centerPoint = [self.topSuperView convertPoint:viewCenterPoint toView:self.superview];
    self.zm_centerX = centerPoint.x;
}

- (void)centerYEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewCenterPoint = [superView convertPoint:view.center toView:self.topSuperView];
    CGPoint centerPoint = [self.topSuperView convertPoint:viewCenterPoint toView:self.superview];
    self.zm_centerY = centerPoint.y;
}

- (void)centerEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewCenterPoint = [superView convertPoint:view.center toView:self.topSuperView];
    CGPoint centerPoint = [self.topSuperView convertPoint:viewCenterPoint toView:self.superview];
    self.zm_centerX = centerPoint.x;
    self.zm_centerY = centerPoint.y;
}


- (void)topEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewOrigin = [superView convertPoint:view.zm_origin toView:self.topSuperView];
    CGPoint newOrigin = [self.topSuperView convertPoint:viewOrigin toView:self.superview];
    
    self.zm_y = newOrigin.y;
}

- (void)bottomEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewOrigin = [superView convertPoint:view.zm_origin toView:self.topSuperView];
    CGPoint newOrigin = [self.topSuperView convertPoint:viewOrigin toView:self.superview];
    
    self.zm_y = newOrigin.y + view.zm_height - self.zm_height;
}

- (void)leftEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewOrigin = [superView convertPoint:view.zm_origin toView:self.topSuperView];
    CGPoint newOrigin = [self.topSuperView convertPoint:viewOrigin toView:self.superview];
    
    self.zm_x = newOrigin.x;
}

- (void)rightEqualToView:(UIView *)view {
    UIView *superView = view.superview ? view.superview : view;
    CGPoint viewOrigin = [superView convertPoint:view.zm_origin toView:self.topSuperView];
    CGPoint newOrigin = [self.topSuperView convertPoint:viewOrigin toView:self.superview];
    
    self.zm_x = newOrigin.x + view.zm_width - self.zm_width;
}

#pragma mark Fill
- (void)fillWidth
{
    self.zm_width = self.superview.zm_width;
    self.zm_x = 0;
}

- (void)fillHeight
{
    self.zm_height = self.superview.zm_height;
    self.zm_y = 0;
}

- (void)fill
{
    self.frame = CGRectMake(0, 0, self.superview.zm_width, self.superview.zm_height);
}

#pragma mark iPhoneX

- (CGFloat)safeAreaBottomGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            if (self.superview.safeAreaLayoutGuide.layoutFrame.size.height > 0) {
                gap = @((self.superview.zm_height - self.superview.safeAreaLayoutGuide.layoutFrame.origin.y - self.superview.safeAreaLayoutGuide.layoutFrame.size.height));
            } else {
                gap = nil;
            }
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)safeAreaTopGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.y);
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)safeAreaLeftGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.x);
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)safeAreaRightGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @((self.superview.zm_width - self.superview.safeAreaLayoutGuide.layoutFrame.origin.x - self.superview.safeAreaLayoutGuide.layoutFrame.size.width));
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}


#pragma mark- TopSuperView

- (UIView *)topSuperView
{
    UIView *topSuperView = self.superview;
    if (topSuperView == nil) {
        topSuperView = self;
    } else {
        while (topSuperView.superview) {
            topSuperView = topSuperView.superview;
        }
    }
    return topSuperView;
}



@end
